/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2016.01.31                                          *
 *                                                                       *
 *************************************************************************/

//declaration header
#include "COMMON/equa/ElasticMechanicsEquationEnsemble.h"

//LIBMESH headers

//COMMON headers
#include "COMMON/info/InfoManager.h"
#include "COMMON/info/CommonInfo.h"
#include "COMMON/tbox/LogMessage.h"



namespace FreeMAPs
{

ElasticMechanicsEquationEnsemble::ElasticMechanicsEquationEnsemble (
    const std::string& parent_name,
    const std::string& object_name/*,
    const int sys_id*/):
    Parent (parent_name, object_name/*, sys_id*/),
    d_plane_structual_type (PlaneStructualType::PLANE_STRESS),
    d_var_displacement (NULL),
    d_var_strain (NULL),
    d_var_stress (NULL),
    d_coef_young_modulus_xx_name ("YOUNG_MODULUS"),
    d_coef_young_modulus_yy_name ("YOUNG_MODULUS"),
    d_coef_young_modulus_zz_name ("YOUNG_MODULUS"),
    d_coef_poisson_ratio_xy_name ("POISSON_RATIO"),
    d_coef_poisson_ratio_yz_name ("POISSON_RATIO"),
    d_coef_poisson_ratio_zx_name ("POISSON_RATIO"),
    d_coef_shear_modulus_xy_name ("SHEAR_MODULUS"),
    d_coef_shear_modulus_yz_name ("SHEAR_MODULUS"),
    d_coef_shear_modulus_zx_name ("SHEAR_MODULUS"),
    d_coef_thermal_expansion_coef_x_name ("THERMAL_EXPANSION_COEF"),
    d_coef_thermal_expansion_coef_y_name ("THERMAL_EXPANSION_COEF"),
    d_coef_thermal_expansion_coef_z_name ("THERMAL_EXPANSION_COEF")
{}



ElasticMechanicsEquationEnsemble::~ElasticMechanicsEquationEnsemble ()
{}



void
ElasticMechanicsEquationEnsemble::get_info_for_derived_object_from_input (
    const InputDatabase* db)
{
#if 0
    this->prepare_for_use (db);

    db->insert_allowable_key ("plane_structual_type");
    db->insert_allowable_key ("var_displacement_name");
    db->insert_allowable_key ("var_strain_name");
    db->insert_allowable_key ("var_stress_name");
    db->insert_allowable_key ("coef_young_modulus_xx");
    db->insert_allowable_key ("coef_young_modulus_yy");
    db->insert_allowable_key ("coef_young_modulus_zz");
    db->insert_allowable_key ("coef_poisson_ratio_xy");
    db->insert_allowable_key ("coef_poisson_ratio_yz");
    db->insert_allowable_key ("coef_poisson_ratio_zx");
    db->insert_allowable_key ("coef_shear_modulus_xy");
    db->insert_allowable_key ("coef_shear_modulus_yz");
    db->insert_allowable_key ("coef_shear_modulus_zx");
    db->insert_allowable_key ("coef_thermal_expansion_coef_x");
    db->insert_allowable_key ("coef_thermal_expansion_coef_y");
    db->insert_allowable_key ("coef_thermal_expansion_coef_z");

    db->check_allowable_keys ();

    const CoefficientInfo* coef_info = InfoManager::get_instance ()->get_coefficient_info ();

    /*
     * build plane_structual_type
     */
    {
        db->check_optional_key ("plane_structual_type", DataType::STRING, true, false);
        d_plane_structual_type = db->get_enum_with_default ("plane_structual_type", d_plane_structual_type);
    }

    /*
     * build displacement_name
     */
    {
        d_var_displacement = this->get_variable_from_database (
                                 db,
                                 "var_displacement_name",
                                 VariableType::VECTOR);
        FREEMAPS_ASSERT_VALID_POINTER (d_var_displacement);
        d_var_displacement->set_dependency_type (DependencyType::BASE);
        d_var_displacement->attach_equation_ensemble (this);
    }

    /*
     * build strain_name
     */
    {
        d_var_strain = this->get_variable_from_database (
                           db,
                           "var_strain_name",
                           VariableType::TENSOR);
        FREEMAPS_ASSERT_VALID_POINTER (d_var_strain);
        d_var_strain->set_dependency_type (DependencyType::DERIVED);
        d_var_strain->attach_equation_ensemble (this);
        d_var_strain->get_variable_data()->set_data_type (VariableDataType::STD_VECTOR);
    }

    /*
     * build stress_name
     */
    {
        d_var_stress = this->get_variable_from_database (
                           db,
                           "var_stress_name",
                           VariableType::TENSOR);
        FREEMAPS_ASSERT_VALID_POINTER (d_var_stress);
        d_var_stress->set_dependency_type (DependencyType::DERIVED);
        d_var_stress->attach_equation_ensemble (this);
        d_var_stress->get_variable_data()->set_data_type (VariableDataType::STD_VECTOR);
    }

    /*
     * build coef_young_modulus_xx
     */
    {
        db->check_optional_key ("coef_young_modulus_xx", DataType::STRING, true, false);
        d_coef_young_modulus_xx_name = db->get_string_with_default ("coef_young_modulus_xx", d_coef_young_modulus_xx_name);
        if (!coef_info->has_coefficient (d_coef_young_modulus_xx_name))
        {
            LogMessage::use_improper_string_value (
                db,
                "coef_young_modulus_xx",
                d_coef_young_modulus_xx_name,
                "it should be a coefficient name set in:\n\"base_information --> coefficient_info --> coef_names\"",
                Utilities::get_map_keys (coef_info->get_coefficients ()));
        }
        coef_info->get_coefficient (d_coef_young_modulus_xx_name)->set_used_flag ();

        this->add_key_for_checking_consistence ("coef_young_modulus_xx", "check if all region have set the coefficient.");
    }

    /*
     * build coef_young_modulus_yy
     */
    {
        db->check_optional_key ("coef_young_modulus_yy", DataType::STRING, true, false);
        d_coef_young_modulus_yy_name = db->get_string_with_default ("coef_young_modulus_yy", d_coef_young_modulus_yy_name);
        if (!coef_info->has_coefficient (d_coef_young_modulus_yy_name))
        {
            LogMessage::use_improper_string_value (
                db,
                "coef_young_modulus_yy",
                d_coef_young_modulus_yy_name,
                "it should be a coefficient name set in:\n\"base_information --> coefficient_info --> coef_names\"",
                Utilities::get_map_keys (coef_info->get_coefficients ()));
        }
        coef_info->get_coefficient (d_coef_young_modulus_yy_name)->set_used_flag ();

        this->add_key_for_checking_consistence ("coef_young_modulus_yy", "check if all region have set the coefficient.");
    }

    /*
     * build coef_young_modulus_zz
     */
    {
        db->check_optional_key ("coef_young_modulus_zz", DataType::STRING, true, false);
        d_coef_young_modulus_zz_name = db->get_string_with_default ("coef_young_modulus_zz", d_coef_young_modulus_zz_name);
        if (!coef_info->has_coefficient (d_coef_young_modulus_zz_name))
        {
            LogMessage::use_improper_string_value (
                db,
                "coef_young_modulus_zz",
                d_coef_young_modulus_zz_name,
                "it should be a coefficient name set in:\n\"base_information --> coefficient_info --> coef_names\"",
                Utilities::get_map_keys (coef_info->get_coefficients ()));
        }
        coef_info->get_coefficient (d_coef_young_modulus_zz_name)->set_used_flag ();

        this->add_key_for_checking_consistence ("coef_young_modulus_zz", "check if all region have set the coefficient.");
    }

    /*
     * build coef_poisson_ratio_xy
     */
    {
        db->check_optional_key ("coef_poisson_ratio_xy", DataType::STRING, true, false);
        d_coef_poisson_ratio_xy_name = db->get_string_with_default ("coef_poisson_ratio_xy", d_coef_poisson_ratio_xy_name);
        if (!coef_info->has_coefficient (d_coef_poisson_ratio_xy_name))
        {
            LogMessage::use_improper_string_value (
                db,
                "coef_poisson_ratio_xy",
                d_coef_poisson_ratio_xy_name,
                "it should be a coefficient name set in:\n\"base_information --> coefficient_info --> coef_names\"",
                Utilities::get_map_keys (coef_info->get_coefficients ()));
        }
        coef_info->get_coefficient (d_coef_poisson_ratio_xy_name)->set_used_flag ();

        this->add_key_for_checking_consistence ("coef_poisson_ratio_xy", "check if all region have set the coefficient.");
    }

    /*
     * build coef_poisson_ratio_yz
     */
    {
        db->check_optional_key ("coef_poisson_ratio_yz", DataType::STRING, true, false);
        d_coef_poisson_ratio_yz_name = db->get_string_with_default ("coef_poisson_ratio_yz", d_coef_poisson_ratio_yz_name);
        if (!coef_info->has_coefficient (d_coef_poisson_ratio_yz_name))
        {
            LogMessage::use_improper_string_value (
                db,
                "coef_poisson_ratio_yz",
                d_coef_poisson_ratio_yz_name,
                "it should be a coefficient name set in:\n\"base_information --> coefficient_info --> coef_names\"",
                Utilities::get_map_keys (coef_info->get_coefficients ()));
        }
        coef_info->get_coefficient (d_coef_poisson_ratio_yz_name)->set_used_flag ();

        this->add_key_for_checking_consistence ("coef_poisson_ratio_yz", "check if all region have set the coefficient.");
    }

    /*
     * build coef_poisson_ratio_zx
     */
    {
        db->check_optional_key ("coef_poisson_ratio_zx", DataType::STRING, true, false);
        d_coef_poisson_ratio_zx_name = db->get_string_with_default ("coef_poisson_ratio_zx", d_coef_poisson_ratio_zx_name);
        if (!coef_info->has_coefficient (d_coef_poisson_ratio_zx_name))
        {
            LogMessage::use_improper_string_value (
                db,
                "coef_poisson_ratio_zx",
                d_coef_poisson_ratio_zx_name,
                "it should be a coefficient name set in:\n\"base_information --> coefficient_info --> coef_names\"",
                Utilities::get_map_keys (coef_info->get_coefficients ()));
        }
        coef_info->get_coefficient (d_coef_poisson_ratio_zx_name)->set_used_flag ();

        this->add_key_for_checking_consistence ("coef_poisson_ratio_zx", "check if all region have set the coefficient.");
    }

    /*
     * build coef_shear_modulus_xy,
     * note that shear modulus is not necessary set. so check it in check_consistence(), not here.
     */
    {
        db->check_optional_key ("coef_shear_modulus_xy", DataType::STRING, true, false);
        d_coef_shear_modulus_xy_name = db->get_string_with_default ("coef_shear_modulus_xy", d_coef_shear_modulus_xy_name);
        if (coef_info->has_coefficient (d_coef_shear_modulus_xy_name))
            coef_info->get_coefficient (d_coef_shear_modulus_xy_name)->set_used_flag ();
        this->add_key_for_checking_consistence ("coef_shear_modulus_xy", "check if all region have set the coefficient.");
    }

    /*
     * build coef_shear_modulus_yz
     */
    {
        db->check_optional_key ("coef_shear_modulus_yz", DataType::STRING, true, false);
        d_coef_shear_modulus_yz_name = db->get_string_with_default ("coef_shear_modulus_yz", d_coef_shear_modulus_yz_name);
        if (coef_info->has_coefficient (d_coef_shear_modulus_yz_name))
            coef_info->get_coefficient (d_coef_shear_modulus_yz_name)->set_used_flag ();
        this->add_key_for_checking_consistence ("coef_shear_modulus_yz", "check if all region have set the coefficient.");
    }

    /*
     * build coef_shear_modulus_zx
     */
    {
        db->check_optional_key ("coef_shear_modulus_zx", DataType::STRING, true, false);
        d_coef_shear_modulus_zx_name = db->get_string_with_default ("coef_shear_modulus_zx", d_coef_shear_modulus_zx_name);
        if (coef_info->has_coefficient (d_coef_shear_modulus_zx_name))
            coef_info->get_coefficient (d_coef_shear_modulus_zx_name)->set_used_flag ();
        this->add_key_for_checking_consistence ("coef_shear_modulus_zx", "check if all region have set the coefficient.");
    }
    /*
    * build coef_thermal_expansion_coef_x
    */
    {
        db->check_optional_key ("coef_thermal_expansion_coef_x", DataType::STRING, true, false);
        d_coef_thermal_expansion_coef_x_name = db->get_string_with_default ("coef_thermal_expansion_coef_x", d_coef_thermal_expansion_coef_x_name);
        if (coef_info->has_coefficient (d_coef_thermal_expansion_coef_x_name))
            coef_info->get_coefficient (d_coef_thermal_expansion_coef_x_name)->set_used_flag ();
        this->add_key_for_checking_consistence ("coef_thermal_expansion_coef_x", "check if all region have set the coefficient.");
    }
    /*
    * build coef_thermal_expansion_coef_y
    */
    {
        db->check_optional_key ("coef_thermal_expansion_coef_y", DataType::STRING, true, false);
        d_coef_thermal_expansion_coef_y_name = db->get_string_with_default ("coef_thermal_expansion_coef_y", d_coef_thermal_expansion_coef_y_name);
        if (coef_info->has_coefficient (d_coef_thermal_expansion_coef_y_name))
            coef_info->get_coefficient (d_coef_thermal_expansion_coef_y_name)->set_used_flag ();
        this->add_key_for_checking_consistence ("coef_thermal_expansion_coef_y", "check if all region have set the coefficient.");
    }
    /*
    * build coef_thermal_expansion_coef_z
    */
    {
        db->check_optional_key ("coef_thermal_expansion_coef_z", DataType::STRING, true, false);
        d_coef_thermal_expansion_coef_z_name = db->get_string_with_default ("coef_thermal_expansion_coef_z", d_coef_thermal_expansion_coef_z_name);
        if (coef_info->has_coefficient (d_coef_thermal_expansion_coef_z_name))
            coef_info->get_coefficient (d_coef_thermal_expansion_coef_z_name)->set_used_flag ();
        this->add_key_for_checking_consistence ("coef_thermal_expansion_coef_z", "check if all region have set the coefficient.");
    }
#endif
}



std::string
ElasticMechanicsEquationEnsemble::get_info_from_derived_object () const
{
    std::stringstream ss;
    ss << "equations\n{\n";

//    ss << LogMessage::get_prefix (ONE_TAB) << "plane_structual_type  = \"" << Utilities::enum_to_string (d_plane_structual_type) << "\"\n";
//    ss << LogMessage::get_prefix (ONE_TAB) << "var_displacement_name = \"" << d_var_displacement->get_name () << "\"\n";
//    ss << LogMessage::get_prefix (ONE_TAB) << "var_strain_name       = \"" << d_var_strain->get_name () << "\"\n";
//    ss << LogMessage::get_prefix (ONE_TAB) << "var_stress_name       = \"" << d_var_stress->get_name () << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "var_displacement_name = \"" << "dis" << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "var_strain_name       = \"" << "strain" << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "var_stress_name       = \"" << "stress" << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_young_modulus_xx = \"" << d_coef_young_modulus_xx_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_young_modulus_yy = \"" << d_coef_young_modulus_yy_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_young_modulus_zz = \"" << d_coef_young_modulus_zz_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_poisson_ratio_xy = \"" << d_coef_poisson_ratio_xy_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_poisson_ratio_yz = \"" << d_coef_poisson_ratio_yz_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_poisson_ratio_zx = \"" << d_coef_poisson_ratio_zx_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_shear_modulus_xy = \"" << d_coef_shear_modulus_xy_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_shear_modulus_yz = \"" << d_coef_shear_modulus_yz_name << "\"\n";
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_shear_modulus_zx = \"" << d_coef_shear_modulus_zx_name << "\"\n";

    //
    ss << LogMessage::get_prefix (ONE_TAB) << "coef_thermal_expansion_coef_x = \"" << "THERMAL_EXPANSION_COEF" << "\"\n";

    ss << "}";

    return ss.str ();
}

} // namespace FreeMAPs
